package com.zy.service;

import com.aliyun.oss.OSS;
import com.aliyun.oss.model.PutObjectRequest;
import com.zy.configs.OssConfig;
import com.zy.utils.FileTypeValidator;
import lombok.extern.java.Log;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;

/**
 * @program: shopping153_cloud
 * @description: 文件上传并且去重
 * @author: zy
 * @create: 2025-08-19 15:14
 */
@Service
@Log     // spring boot的默认日志框架是logback
public class FileDeduplicationService {

    private static final String REDIS_IMAGE_MD5_PREFIX="image:md5:";  //前缀
    private static final long REDIS_KEY_TTL_DAYS=30*12;    //在redis中存储的时间, 单位是天

    @Autowired
    private OSS ossClient;
    @Autowired
    private OssConfig ossConfig;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public String processAndGetFileUrl(MultipartFile file ) throws IOException {
        String contentType = file.getContentType();   //文件的MIME类型
        String originalFilename = file.getOriginalFilename(); //原始文件名
        if (!FileTypeValidator.isValidType(contentType, originalFilename)) {
            throw new IllegalArgumentException("Invalid file type: " + originalFilename);
        }
        String md5Hash;  //文件的MD5值
        try (InputStream is = file.getInputStream()) {
            md5Hash = DigestUtils.md5Hex(is); // 工具类计算 md5码
        } catch (IOException e) {
            log.severe("Failed to calculate MD5 hash for file:"+ originalFilename);
            throw new RuntimeException("Failed to process file: " + originalFilename, e);
        }
        //到redis中检查 是否有这MD5值
        String redisKey=REDIS_IMAGE_MD5_PREFIX+md5Hash;      // 键: "image:md4:xxxxx"
        String existingFileUrl = this.stringRedisTemplate.opsForValue().get(   redisKey );
        if (existingFileUrl != null && !existingFileUrl.isEmpty()) {
            log.info("Duplicate file detected for MD5: "+ md5Hash+". Returning existing URL: "+existingFileUrl);
            stringRedisTemplate.expire(redisKey, REDIS_KEY_TTL_DAYS, TimeUnit.DAYS); // 刷新过期时间
            return existingFileUrl;  //返回重复文件的地址
        }
        log.info("New unique file detected for MD5: "+md5Hash+". Uploading to OSS.");
        // 4. Upload to OSS (if not a duplicate)
        String fileExtension = "";
        if (originalFilename != null && originalFilename.contains(".")) {
            fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
        }
        //  新上传的文件 的文件名:  md5+后缀名
        String objectKey = "files/" + md5Hash + fileExtension;  // 上传成功后的 地址:   files/md5+后缀名.jpg
        PutObjectRequest putObjectRequest = new PutObjectRequest(ossConfig.getBucketName(), objectKey, file.getInputStream());
        ossClient.putObject(putObjectRequest);
        //拼接上传成功后的路径
        String newFileUrl = ossConfig.getUrlPrefix()+ File.separator  + objectKey;
        //将md5码与这个地址保存到redis中
        this.stringRedisTemplate.opsForValue().set(   redisKey,  newFileUrl,  REDIS_KEY_TTL_DAYS, TimeUnit.DAYS);
        log.info(   "文件上传成功, 地址为: "+newFileUrl+", redis中的md5码为:"+ redisKey );
        return newFileUrl;
    }


}
